# coding=utf-8
"""
作者:董新强 
创建时间:2021年8月31日
描述:发布代码
"""
import os
import re
import shutil
from compileall import compile_dir
from os import walk
from os.path import join, isdir, dirname


def red(tag: str) -> str:
    """
    将需要打印再控制台的字设置为红色
    """
    return " \033[4;31m{}\033[0m ".format(tag)


def printr(tag, *args):
    """
    在控制台显示为红色背景的文字
    """
    print("\033[0;30;41m【{}】\033[0m".format(tag), *args)


def printg(tag, *args):
    """
    在控制台显示为红色背景的文字
    """
    print("\033[0;30;42m【{}】\033[0m".format(tag), *args)


class Publish:
    note_pattern = re.compile(b'#.*')

    @classmethod
    def delete_note(cls, fname):
        """
        删除注释
        """
        lines = open(fname, "rb").readlines()
        new_lines = []
        for idx, line in enumerate(lines):
            if not idx and line.startswith(b'#'): continue

            single_count, double_count = 0, 0
            if b'#' in line:
                for c in line[:line.index(b'#')]:  # 如果#前含有奇数个引号就认为#是字符串的一部分
                    if c == 39: single_count += 1
                    if c == 34: double_count += 1
            if single_count % 2 == 0 and double_count % 2 == 0:
                new_lines.append(re.sub(cls.note_pattern, b'', line))
            else:
                new_lines.append(line)

        with open(fname, 'wb') as f:
            f.writelines(new_lines)

    @classmethod
    def compile(cls, source, destination, del_files):
        if isdir(destination):
            shutil.rmtree(destination)

        # # 拷贝都新目录进行操作
        print('复制到新文件夹...')
        if not shutil.copytree(source, destination, ignore=shutil.ignore_patterns('.git')):
            printr('失败', 'shutil.copytree->', destination)
            return

        # 删除注释
        print('删除注释...')
        for path, dirs, files in walk(destination):
            for f in files:
                if f == 'publish.py' or not f.endswith('.py'): continue
                if f in del_files:
                    os.remove(join(path, f))
                    continue

                Publish.delete_note(join(path, f))

        # 编译文件
        print('编译文件...')
        if not compile_dir(destination, force=True):
            printr('失败', 'compile_dir->', destination)
            return

        # 删除.py文件
        print('删除源文件...')
        for path, dirs, files in walk(destination):
            for f in files:
                if f.endswith('.cnf'):
                    continue

                if not f.endswith('.pyc'):
                    os.remove(join(path, f))
                    continue

                pyc = '{}.pyc'.format('.'.join(f.split('.')[:-2]))
                if not shutil.move(join(path, f), join(dirname(path), pyc)):
                    printr('失败', 'shutil.move->', join(path, f), join(dirname(path), pyc))
                    return

        printg('成功', '编译完成')


if __name__ == '__main__':
    def run():
        del_files = {'entity_tools.py', '数据库比较.py', 'documents', 'publish.py'}

        source_code_dir = input('源码路径:\t')
        if not source_code_dir:
            printr('失败', '路径错误')
            return

        pyc_dir = source_code_dir + '_pycs'

        try:
            os.remove(pyc_dir)
        except:
            pass

        Publish.compile(source_code_dir, pyc_dir, del_files)

        input('按 Enter 键结束')


    run()